// Keywords: nonWF, non-Wright-Fisher, continuous space, continuous spatial landscape, selfing, spatial competition, spatial mate choice

initialize() {
	initializeSLiMModelType("nonWF");
	initializeSLiMOptions(dimensionality="xy");
	defineConstant("K", 300);   // carrying-capacity density
	defineConstant("S", 0.1);   // SIGMA_S, the spatial interaction width
	
	initializeMutationType("m1", 0.5, "f", 0.0);
	m1.convertToSubstitution = T;
	
	initializeGenomicElementType("g1", m1, 1.0);
	initializeGenomicElement(g1, 0, 99999);
	initializeMutationRate(1e-7);
	initializeRecombinationRate(1e-8);
	
	// spatial competition
	initializeInteractionType(1, "xy", reciprocal=T, maxDistance=S * 3);
	i1.setInteractionFunction("n", 1.0, S);
	
	// spatial mate choice
	initializeInteractionType(2, "xy", reciprocal=T, maxDistance=0.1);
}
2: first() {
	// look for mates
	i2.evaluate(p1);
}
reproduction() {
	// choose our nearest neighbor as a mate, within the max distance
	mate = i2.nearestNeighbors(individual, 1);
	
	for (i in seqLen(rpois(1, 0.1)))
	{
		if (mate.size())
			offspring = subpop.addCrossed(individual, mate);
		else
			offspring = subpop.addSelfed(individual);
		
		// set offspring position
		do pos = individual.spatialPosition + rnorm(2, 0, 0.02);
		while (!p1.pointInBounds(pos));
		offspring.setSpatialPosition(pos);
	}
}
1 early() {
	sim.addSubpop("p1", 1);
	
	// random initial positions
	p1.individuals.setSpatialPosition(p1.pointUniform(1));
}
early() {
	i1.evaluate(p1);
	
	// spatial competition provides density-dependent selection
	inds = p1.individuals;
	competition = i1.localPopulationDensity(inds);
	inds.fitnessScaling = K / competition;
}
late()
{
	// move around a bit
	for (ind in p1.individuals)
	{
		do newPos = ind.spatialPosition + runif(2, -0.01, 0.01);
		while (!p1.pointInBounds(newPos));
		ind.setSpatialPosition(newPos);
	}
}
10000 late() {
	sim.outputFixedMutations();
}
